<?php
/**
 * Created by PhpStorm.
 * User: cephei
 * Date: 11/26/15
 * Time: 2:04 PM
 */
namespace Plugins\PAC;

use Core\PluginContainer;

class Plugin_PAC{
    private $db;

    public function __construct(){
        $this->db = PluginContainer::getInstance()->singletonMake('database');
        if($this->db->first("select count(1) as c from plg_pac_rules where user=0")->c<=0){
            $f = file(ROOT_PATH.'/Plugins/PAC/gfwlist.txt');
            $this->importGFWList($f);
        }
    }

    public function appendRule($name,$url,$proxy,$type,$userId){
        $url = trim($url);
        $exist = $this->db->first("select count(1) as c from plg_pac_rules where url='$url' and user='$userId'")->c;
        if($exist>0){
            $this->db->update("plg_pac_rules",["proxy"=>$proxy,"type"=>$type,"user"=>$userId]," where url='$url''");
        }else{
            $this->db->insert("plg_pac_rules",["name"=>$name,"url"=>$url,"proxy"=>$proxy,"type"=>$type,"user"=>$userId]);
        }

    }

    public function setDefaultProxy($proxy){
        $this->db->update("plg_settings",["value"=>$proxy]," where attribute='gfwproxy'");
    }

    public function appendProxy($name,$type,$url,$port){
        $exist = $this->db->first("select count(1) as c from plg_pac_proxys where name='$name'")->c;
        if($exist>0){
            $this->db->update("plg_pac_proxys",["type"=>$type,"url"=>$url,"port"=>$port]," where name='$name''");
        }else{
            $this->db->insert("plg_pac_proxys",["name"=>$name,"type"=>$type,"url"=>$url,"port"=>$port]);
        }
    }

    public function getProxyList(){
        return json_encode($this->db->get("select * from plg_pac_proxys"));
    }

    public function importGFWList($array){
        foreach($array as $item){
            if(strpos($item,'!')===0||$item=="\n") {
                if($item=='!-----Whitelist-----')
                    return;
                continue;
            }
            if(strpos($item,'|')===0){
                $url = str_replace('|','',$item);
                $this->appendRule($url,$url,'',1,0);
                continue;
            }
            if(strpos($item,'@')===0){
                $url = str_replace('@','',$item);
                $url = str_replace('|','',$url);
                $this->appendRule($url,$url,'',1,0);
                continue;
            }
            if(strpos($item,'/')===0){
                $this->appendRule($item,$item,'',3,0);
                continue;
            }
            $this->appendRule($item,$item,'',2,0);
        }

    }

    public function getPACFile($userId,$mandatoryProxy=""){
        $rules = $this->db->get("select * from plg_pac_rules where user=$userId");
        $proxys = $this->db->get("select * from plg_pac_proxys");
        $gfwProxy = $this->db->first("select value from plg_settings where attribute='gfwproxy'")->value;
        $javaScript =[];
        $javaScript[]='var FindProxyForURL = function(init, profiles) {';
        $javaScript[]='    return function(url, host) {';
        $javaScript[]='var result = init, scheme = url.substr(0, url.indexOf(":"));';
        $javaScript[]='        do {';
        $javaScript[]='            result = profiles[result];';
        $javaScript[]='            if (typeof result === "function"){';
        $javaScript[]='                 result = result(url, host, scheme);';
        $javaScript[]='            }';
        $javaScript[]='        } while (typeof result !== "string" || result.charCodeAt(0) === 43);';
        $javaScript[]='        return result;';
        $javaScript[]='    };';
        $javaScript[]='}("+php_pac",{';
        $javaScript[]='    "+php_pac": function(url, host, scheme) {';
        foreach ($rules as $rule) {
            $url = $rule->url;
            $proxy = $rule->proxy;
            if ($userId == 0) {
                $proxy = $gfwProxy;
            }
            if($mandatoryProxy!=""){
                $proxy = $mandatoryProxy;
            }
            switch ($rule->type) {
                case 1:
                    if (strpos($url, '*.') === 0) {
                        $url = str_replace('*.', '', $url);
                    }
                    $url = str_replace('.', '\.', $url);
                    $url = str_replace('/', '\/', $url);
                    $url = str_replace('*', '.*', $url);
                    $prefix = '(?:^|\.)';
                    $target = 'host';
                    if(strpos($url,'http')===0) {
                        $prefix = '^';
                        $target = 'url';
                    }
                        $javaScript[] = "if (/$prefix$url$/.test($target)) return \"+$proxy\";";
                    break;
                case 2:
                    $javaScript[] = "if (scheme === \"http\" && url.indexOf(\"$url\") >= 0) return \"+$proxy\";";
                    break;
                case 3:
                    $url = substr($url,1);
                    $url = substr($url,0,strlen($url)-1);
                    $url = str_replace('/', '\/', $url);
                    $url = str_replace('.', '\.', $url);
                    $url = str_replace('\.*', '.*', $url);
                    $javaScript[] = "if (/$url/.test(url)) return \"+$proxy\";";
                    break;
            }

        }
        $javaScript[]='return "DIRECT";';
        $javaScript[] ='}';
        foreach($proxys as $proxy){
            $javaScript[] =", \"+$proxy->name\": function(url,host,scheme){";
            $javaScript[] ='if (host === "[::1]" || host === "localhost" || host === "127.0.0.1"){ return "DIRECT";}';
            $javaScript[] ='else{ return "'.$proxy->type.' '.$proxy->url.':'.$proxy->port.'";}';
            $javaScript[] ='}';
        }
        $javaScript[]="});";
        return implode('',$javaScript);
    }
}